<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;
use Overtrue\Pinyin\Pinyin;

class Post extends Model
{
    use HasFactory;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'title',
        'slug',
        'content',
        'user_id',
        'bar_id',
        'images',
        'views',
        'like_count',
        'reply_count',
        'is_pinned',
        'is_essence',
        'pinned_at',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'images' => 'array',
        'views' => 'integer',
        'like_count' => 'integer',
        'reply_count' => 'integer',
        'is_pinned' => 'boolean',
        'is_essence' => 'boolean',
        'pinned_at' => 'datetime',
    ];

    /**
     * 帖子作者
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * 所属贴吧
     */
    public function bar(): BelongsTo
    {
        return $this->belongsTo(Bar::class);
    }

    /**
     * 帖子点赞
     */
    public function likes(): HasMany
    {
        return $this->hasMany(PostLike::class);
    }

    /**
     * 帖子收藏
     */
    public function favorites(): HasMany
    {
        return $this->hasMany(Favorite::class);
    }

    /**
     * 帖子回复
     */
    public function replies(): HasMany
    {
        return $this->hasMany(Reply::class)->whereNull('parent_id')->orderBy('created_at', 'asc');
    }

    /**
     * 所有回复（包括楼中楼）
     */
    public function allReplies(): HasMany
    {
        return $this->hasMany(Reply::class)->orderBy('created_at', 'asc');
    }

    /**
     * 判断用户是否已点赞
     */
    public function isLikedBy(?User $user): bool
    {
        if (!$user) {
            return false;
        }

        return $this->likes()->where('user_id', $user->id)->exists();
    }

    /**
     * 判断用户是否已收藏
     */
    public function isFavoritedBy(?User $user): bool
    {
        if (!$user) {
            return false;
        }

        return $this->favorites()->where('user_id', $user->id)->exists();
    }

    /**
     * 判断是否为作者
     */
    public function isAuthor(User $user): bool
    {
        return $this->user_id === $user->id;
    }

    /**
     * 增加浏览数
     */
    public function incrementViews(): void
    {
        $this->increment('views');
    }

    /**
     * Get the route key for the model.
     */
    public function getRouteKeyName()
    {
        return 'slug';
    }

    /**
     * Boot the model.
     */
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($post) {
            if (empty($post->slug)) {
                // 生成临时 slug（不含 ID）
                $tempSlug = static::generateSlug($post->title);
                // 先设置临时 slug，创建后再更新为包含 ID 的 slug
                $post->slug = $tempSlug;
            }
        });

        static::created(function ($post) {
            // 创建后更新 slug（添加 ID 前缀以保证唯一性和可读性）
            // 使用 withoutEvents 避免触发 updating 事件循环
            if (!preg_match('/^\d+-/', $post->slug)) {
                static::withoutEvents(function () use ($post) {
                    $post->update(['slug' => $post->id . '-' . $post->slug]);
                });
            }
        });
    }

    /**
     * 生成 slug（使用拼音转换）
     */
    protected static function generateSlug(string $title): string
    {
        $pinyin = new Pinyin();
        // 使用 permalink 方法，自动转换为拼音并用连字符分隔
        $pinyinSlug = $pinyin->permalink($title, '-');
        
        // 如果转为空（纯特殊字符），使用随机字符串
        if (empty($pinyinSlug)) {
            $pinyinSlug = 'post-' . Str::random(8);
        }
        
        // 限制长度（URL 友好）
        $pinyinSlug = Str::limit($pinyinSlug, 80, '');
        
        // 确保唯一性（使用精确匹配而不是 like，避免误匹配）
        // 注意：由于创建后会添加 ID 前缀，这里主要防止临时 slug 冲突
        $slug = $pinyinSlug;
        $counter = 1;
        while (static::where('slug', $slug)->orWhere('slug', 'like', $slug . '-%')->exists()) {
            $slug = $pinyinSlug . '-' . $counter;
            $counter++;
        }
        
        return $slug;
    }
}
